From d42fcbcc999049b13bb5d36a03049fbb633b0869 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 21 Sep 2005 10:11:02 +0000 Subject: [PATCH] Removes redundant/unnecessary __vmread/__vmwrite. Signed-off-by: Jun Nakajima Signed-off-by: Eddie Dong Signed-off-by: Edwin Zhai --- xen/arch/x86/vmx.c | 43 ++++++++++----------- xen/arch/x86/vmx_io.c | 10 +---- xen/arch/x86/vmx_vmcs.c | 57 ++++++++++++---------------- xen/include/asm-x86/vmx.h | 69 ++++++++++++++++++++++++++++++++-- xen/include/asm-x86/vmx_vmcs.h | 3 ++ 5 files changed, 113 insertions(+), 69 deletions(-) diff --git a/xen/arch/x86/vmx.c b/xen/arch/x86/vmx.c index da1016cf92..bb4d9cf942 100644 --- a/xen/arch/x86/vmx.c +++ b/xen/arch/x86/vmx.c @@ -377,12 +377,13 @@ static void inline __update_guest_eip(unsigned long inst_len) static int vmx_do_page_fault(unsigned long va, struct cpu_user_regs *regs) { - unsigned long eip; unsigned long gpa; /* FIXME: PAE */ int result; -#if VMX_DEBUG +#if 0 /* keep for debugging */ { + unsigned long eip; + __vmread(GUEST_RIP, &eip); VMX_DBG_LOG(DBG_LEVEL_VMMU, "vmx_do_page_fault = 0x%lx, eip = %lx, error_code = %lx", @@ -429,9 +430,9 @@ static void vmx_do_no_device_fault(void) clts(); setup_fpu(current); - __vmread(CR0_READ_SHADOW, &cr0); + __vmread_vcpu(CR0_READ_SHADOW, &cr0); if (!(cr0 & X86_CR0_TS)) { - __vmread(GUEST_CR0, &cr0); + __vmread_vcpu(GUEST_CR0, &cr0); cr0 &= ~X86_CR0_TS; __vmwrite(GUEST_CR0, cr0); } @@ -1129,9 +1130,7 @@ static int vmx_set_cr0(unsigned long value) __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); } } - __vmread(GUEST_RIP, &eip); - VMX_DBG_LOG(DBG_LEVEL_1, - "Disabling CR0.PE at %%eip 0x%lx\n", eip); + if (vmx_assist(d, VMX_ASSIST_INVOKE)) { set_bit(VMX_CPU_STATE_ASSIST_ENABLED, &d->arch.arch_vmx.cpu_state); __vmread(GUEST_RIP, &eip); @@ -1370,17 +1369,17 @@ static int vmx_cr_access(unsigned long exit_qualification, struct cpu_user_regs clts(); setup_fpu(current); - __vmread(GUEST_CR0, &value); + __vmread_vcpu(GUEST_CR0, &value); value &= ~X86_CR0_TS; /* clear TS */ __vmwrite(GUEST_CR0, value); - __vmread(CR0_READ_SHADOW, &value); + __vmread_vcpu(CR0_READ_SHADOW, &value); value &= ~X86_CR0_TS; /* clear TS */ __vmwrite(CR0_READ_SHADOW, value); break; case TYPE_LMSW: TRACE_VMEXIT(1,TYPE_LMSW); - __vmread(CR0_READ_SHADOW, &value); + __vmread_vcpu(CR0_READ_SHADOW, &value); value = (value & ~0xF) | (((exit_qualification & LMSW_SOURCE_DATA) >> 16) & 0xF); return vmx_set_cr0(value); @@ -1456,16 +1455,12 @@ static inline void vmx_do_msr_write(struct cpu_user_regs *regs) (unsigned long)regs->edx); } +volatile unsigned long do_hlt_count; /* * Need to use this exit to reschedule */ -static inline void vmx_vmexit_do_hlt(void) +void vmx_vmexit_do_hlt(void) { -#if VMX_DEBUG - unsigned long eip; - __vmread(GUEST_RIP, &eip); -#endif - VMX_DBG_LOG(DBG_LEVEL_1, "vmx_vmexit_do_hlt:eip=%lx", eip); raise_softirq(SCHEDULE_SOFTIRQ); } @@ -1516,13 +1511,9 @@ static inline void vmx_vmexit_do_extint(struct cpu_user_regs *regs) } } +volatile unsigned long do_mwait_count; static inline void vmx_vmexit_do_mwait(void) { -#if VMX_DEBUG - unsigned long eip; - __vmread(GUEST_RIP, &eip); -#endif - VMX_DBG_LOG(DBG_LEVEL_1, "vmx_vmexit_do_mwait:eip=%lx", eip); raise_softirq(SCHEDULE_SOFTIRQ); } @@ -1631,9 +1622,13 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs) return; } - __vmread(GUEST_RIP, &eip); - TRACE_3D(TRC_VMX_VMEXIT, v->domain->domain_id, eip, exit_reason); - TRACE_VMEXIT(0,exit_reason); +#ifdef TRACE_BUFFER + { + __vmread(GUEST_RIP, &eip); + TRACE_3D(TRC_VMX_VMEXIT, v->domain->domain_id, eip, exit_reason); + TRACE_VMEXIT(0,exit_reason); + } +#endif switch (exit_reason) { case EXIT_REASON_EXCEPTION_NMI: diff --git a/xen/arch/x86/vmx_io.c b/xen/arch/x86/vmx_io.c index f0a5357b31..4ad3ae8dc7 100644 --- a/xen/arch/x86/vmx_io.c +++ b/xen/arch/x86/vmx_io.c @@ -891,7 +891,7 @@ asmlinkage void vmx_intr_assist(void) struct vcpu *v = current; highest_vector = find_highest_pending_irq(v, &intr_type); - __vmread(CPU_BASED_VM_EXEC_CONTROL, &cpu_exec_control); + __vmread_vcpu(CPU_BASED_VM_EXEC_CONTROL, &cpu_exec_control); if (highest_vector == -1) { disable_irq_window(cpu_exec_control); @@ -948,14 +948,6 @@ asmlinkage void vmx_intr_assist(void) void vmx_do_resume(struct vcpu *d) { vmx_stts(); - if ( vmx_paging_enabled(d) ) - __vmwrite(GUEST_CR3, pagetable_get_paddr(d->arch.shadow_table)); - else - // paging is not enabled in the guest - __vmwrite(GUEST_CR3, pagetable_get_paddr(d->domain->arch.phys_table)); - - __vmwrite(HOST_CR3, pagetable_get_paddr(d->arch.monitor_table)); - __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom()); if (event_pending(d)) { vmx_check_events(d); diff --git a/xen/arch/x86/vmx_vmcs.c b/xen/arch/x86/vmx_vmcs.c index 85baa632bc..70d94e6371 100644 --- a/xen/arch/x86/vmx_vmcs.c +++ b/xen/arch/x86/vmx_vmcs.c @@ -68,9 +68,6 @@ static inline int construct_vmcs_controls(struct arch_vmx_struct *arch_vmx) error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL, MONITOR_PIN_BASED_EXEC_CONTROLS); - error |= __vmwrite(CPU_BASED_VM_EXEC_CONTROL, - MONITOR_CPU_BASED_EXEC_CONTROLS); - error |= __vmwrite(VM_EXIT_CONTROLS, MONITOR_VM_EXIT_CONTROLS); error |= __vmwrite(VM_ENTRY_CONTROLS, MONITOR_VM_ENTRY_CONTROLS); @@ -117,12 +114,6 @@ struct host_execution_env { unsigned long fs_base; unsigned long gs_base; #endif - - /* control registers */ - unsigned long cr3; - unsigned long cr0; - unsigned long cr4; - unsigned long dr7; }; #define round_pgdown(_p) ((_p)&PAGE_MASK) /* coped from domain.c */ @@ -217,9 +208,33 @@ void vmx_do_launch(struct vcpu *v) /* Update CR3, GDT, LDT, TR */ unsigned int error = 0; unsigned long pfn = 0; + unsigned long cr0, cr4; struct pfn_info *page; struct cpu_user_regs *regs = guest_cpu_user_regs(); + __asm__ __volatile__ ("mov %%cr0,%0" : "=r" (cr0) : ); + + error |= __vmwrite(GUEST_CR0, cr0); + cr0 &= ~X86_CR0_PG; + error |= __vmwrite(CR0_READ_SHADOW, cr0); + error |= __vmwrite(CPU_BASED_VM_EXEC_CONTROL, + MONITOR_CPU_BASED_EXEC_CONTROLS); + + __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (cr4) : ); + +#ifdef __x86_64__ + error |= __vmwrite(GUEST_CR4, cr4 & ~X86_CR4_PSE); +#else + error |= __vmwrite(GUEST_CR4, cr4); +#endif + +#ifdef __x86_64__ + cr4 &= ~(X86_CR4_PGE | X86_CR4_VMXE | X86_CR4_PAE); +#else + cr4 &= ~(X86_CR4_PGE | X86_CR4_VMXE); +#endif + error |= __vmwrite(CR4_READ_SHADOW, cr4); + vmx_stts(); page = (struct pfn_info *) alloc_domheap_page(NULL); @@ -254,7 +269,7 @@ construct_init_vmcs_guest(struct cpu_user_regs *regs, int error = 0; union vmcs_arbytes arbytes; unsigned long dr7; - unsigned long eflags, shadow_cr; + unsigned long eflags; /* MSR */ error |= __vmwrite(VM_EXIT_MSR_LOAD_ADDR, 0); @@ -326,27 +341,7 @@ construct_init_vmcs_guest(struct cpu_user_regs *regs, arbytes.fields.seg_type = 0xb; /* 32-bit TSS (busy) */ error |= __vmwrite(GUEST_TR_AR_BYTES, arbytes.bytes); - - error |= __vmwrite(GUEST_CR0, host_env->cr0); /* same CR0 */ - - /* Initally PG, PE are not set*/ - shadow_cr = host_env->cr0; - shadow_cr &= ~X86_CR0_PG; - error |= __vmwrite(CR0_READ_SHADOW, shadow_cr); /* CR3 is set in vmx_final_setup_guest */ -#ifdef __x86_64__ - error |= __vmwrite(GUEST_CR4, host_env->cr4 & ~X86_CR4_PSE); -#else - error |= __vmwrite(GUEST_CR4, host_env->cr4); -#endif - shadow_cr = host_env->cr4; - -#ifdef __x86_64__ - shadow_cr &= ~(X86_CR4_PGE | X86_CR4_VMXE | X86_CR4_PAE); -#else - shadow_cr &= ~(X86_CR4_PGE | X86_CR4_VMXE); -#endif - error |= __vmwrite(CR4_READ_SHADOW, shadow_cr); error |= __vmwrite(GUEST_ES_BASE, host_env->ds_base); error |= __vmwrite(GUEST_CS_BASE, host_env->cs_base); @@ -403,12 +398,10 @@ static inline int construct_vmcs_host(struct host_execution_env *host_env) host_env->cs_base = 0; __asm__ __volatile__ ("mov %%cr0,%0" : "=r" (crn) : ); - host_env->cr0 = crn; error |= __vmwrite(HOST_CR0, crn); /* same CR0 */ /* CR3 is set in vmx_final_setup_hostos */ __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) : ); - host_env->cr4 = crn; error |= __vmwrite(HOST_CR4, crn); error |= __vmwrite(HOST_RIP, (unsigned long) vmx_asm_vmexit_handler); diff --git a/xen/include/asm-x86/vmx.h b/xen/include/asm-x86/vmx.h index 33b8dd21d8..fa2600e5bc 100644 --- a/xen/include/asm-x86/vmx.h +++ b/xen/include/asm-x86/vmx.h @@ -314,6 +314,57 @@ static always_inline int ___vmread (const unsigned long field, void *ptr, const return 0; } + +static always_inline void __vmwrite_vcpu(unsigned long field, unsigned long value) +{ + struct vcpu *v = current; + + switch(field) { + case CR0_READ_SHADOW: + v->arch.arch_vmx.cpu_shadow_cr0 = value; + break; + case GUEST_CR0: + v->arch.arch_vmx.cpu_cr0 = value; + break; + case CPU_BASED_VM_EXEC_CONTROL: + v->arch.arch_vmx.cpu_based_exec_control = value; + break; + default: + printk("__vmwrite_cpu: invalid field %lx\n", field); + break; + } +} + +static always_inline void __vmread_vcpu(unsigned long field, unsigned long *value) +{ + struct vcpu *v = current; + + switch(field) { + case CR0_READ_SHADOW: + *value = v->arch.arch_vmx.cpu_shadow_cr0; + break; + case GUEST_CR0: + *value = v->arch.arch_vmx.cpu_cr0; + break; + case CPU_BASED_VM_EXEC_CONTROL: + *value = v->arch.arch_vmx.cpu_based_exec_control; + break; + default: + printk("__vmread_cpu: invalid field %lx\n", field); + break; + } + + /* + * __vmwrite() can be used for non-current vcpu, and it's possible that + * the vcpu field is not initialized at that case. + * + */ + if (!*value) { + __vmread(field, value); + __vmwrite_vcpu(field, *value); + } +} + static inline int __vmwrite (unsigned long field, unsigned long value) { unsigned long eflags; @@ -326,6 +377,15 @@ static inline int __vmwrite (unsigned long field, unsigned long value) __save_flags(eflags); if (eflags & X86_EFLAGS_ZF || eflags & X86_EFLAGS_CF) return -1; + + switch(field) { + case CR0_READ_SHADOW: + case GUEST_CR0: + case CPU_BASED_VM_EXEC_CONTROL: + __vmwrite_vcpu(field, value); + break; + } + return 0; } @@ -379,11 +439,12 @@ static inline void vmx_stts(void) { unsigned long cr0; - __vmread(GUEST_CR0, &cr0); - if (!(cr0 & X86_CR0_TS)) + __vmread_vcpu(GUEST_CR0, &cr0); + if (!(cr0 & X86_CR0_TS)) { __vmwrite(GUEST_CR0, cr0 | X86_CR0_TS); + } - __vmread(CR0_READ_SHADOW, &cr0); + __vmread_vcpu(CR0_READ_SHADOW, &cr0); if (!(cr0 & X86_CR0_TS)) __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM); } @@ -393,7 +454,7 @@ static inline int vmx_paging_enabled(struct vcpu *v) { unsigned long cr0; - __vmread(CR0_READ_SHADOW, &cr0); + __vmread_vcpu(CR0_READ_SHADOW, &cr0); return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG); } diff --git a/xen/include/asm-x86/vmx_vmcs.h b/xen/include/asm-x86/vmx_vmcs.h index 9c26ef4f97..c204df2a5d 100644 --- a/xen/include/asm-x86/vmx_vmcs.h +++ b/xen/include/asm-x86/vmx_vmcs.h @@ -74,9 +74,12 @@ struct msr_state{ struct arch_vmx_struct { struct vmcs_struct *vmcs; /* VMCS pointer in virtual */ unsigned long flags; /* VMCS flags */ + unsigned long cpu_cr0; /* copy of guest CR0 */ + unsigned long cpu_shadow_cr0; /* copy of guest read shadow CR0 */ unsigned long cpu_cr2; /* save CR2 */ unsigned long cpu_cr3; unsigned long cpu_state; + unsigned long cpu_based_exec_control; struct msr_state msr_content; void *io_bitmap_a, *io_bitmap_b; }; -- 2.30.2